package cn.geminis.crypto.service.controller;

import cn.geminis.crypto.core.util.SerialNumberUtils;
import cn.geminis.crypto.core.x509.X509Certificate;
import cn.geminis.crypto.csp.AbstractCspFactory;
import cn.geminis.crypto.csp.AbstractSigner;
import cn.geminis.crypto.tsp.TimeStampRequest;
import cn.geminis.crypto.tsp.TimeStampResponseGenerator;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDateTime;

/**
 * @author Allen
 */
@RestController
@RequestMapping("/ts")
@Slf4j
public class TsController {

    private TimeStampResponseGenerator generator;
    private AbstractSigner signer;

    @Autowired
    public TsController(AbstractCspFactory cspFactory) {
        this.signer = cspFactory.createSigner();
        var issuer = new X509Certificate();
        issuer.setSubject("cn=TSA");
        issuer.setSerialNumber(SerialNumberUtils.create());
        issuer.setNotBefore(LocalDateTime.now().plusDays(-1));
        issuer.setNotAfter(LocalDateTime.now().plusDays(1));
        issuer.setPublicKey(signer.getPublicKey());
        ExtendedKeyUsage extendedKeyUsage = new ExtendedKeyUsage(KeyPurposeId.id_kp_timeStamping);
        try {
            issuer.getExtensions().add(new Extension(Extension.extendedKeyUsage, true, extendedKeyUsage.getEncoded()));
        } catch (Exception e) {
            throw new RuntimeException("构建TS生成器错误", e);
        }
        issuer.generate(signer);

        this.generator = new TimeStampResponseGenerator(signer, issuer, "1.2.3.4");
    }

    @GetMapping
    public void request(HttpServletRequest request, HttpServletResponse response) {

        var requestData = new byte[request.getContentLength()];
        try {
            request.getInputStream().read(requestData);
        } catch (IOException e) {
            throw new RuntimeException("读取请求数据错误");
        }

        var tsRequest = new TimeStampRequest(requestData);
        var tsResponse = this.generator.response(tsRequest);
        log.info("generate ts：{}", tsResponse.getToken().getSerialNumber());

        try {
            response.getOutputStream().write(tsResponse.getEncode());
        } catch (IOException e) {
            throw new RuntimeException("写入请求响应数据错误");
        }

    }

}
